package com.wenx.v3system.modular.cloud.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wenx.v3system.modular.cloud.domain.po.*;
import com.wenx.v3system.modular.cloud.mapper.*;
import com.wenx.v3system.modular.cloud.service.SysUserPermissionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 系统用户权限服务实现类
 * 基于Enhanced RBAC权限模型重构
 * 使用v3-system数据源
 * 
 * @author wenx
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysUserPermissionServiceImpl implements SysUserPermissionService {

    // 缓存常量
    private static final String USER_PERMISSIONS_CACHE = "user:permissions";
    private static final String USER_ROLES_CACHE = "user:roles";
    private static final String USER_MENUS_CACHE = "user:menus";
    private static final String USER_DEPT_PERMISSIONS_CACHE = "user:dept:permissions";

    private final SysUserMapper sysUserMapper;
    private final SysUserRoleMapper sysUserRoleMapper;
    private final SysRoleMapper sysRoleMapper;
    private final SysRolePermissionMapper sysRolePermissionMapper;
    private final SysPermissionMapper sysPermissionMapper;
    private final SysRoleMenuMapper sysRoleMenuMapper;

    @Override
    @Cacheable(value = USER_PERMISSIONS_CACHE, key = "#userId")
    public Set<String> getUserPermissions(Long userId) {
        if (userId == null) {
            return Collections.emptySet();
        }

        // 获取用户角色
        Set<Long> roleIds = getUserRoles(userId);
        if (CollectionUtils.isEmpty(roleIds)) {
            return Collections.emptySet();
        }

        // 查询角色权限关联
        LambdaQueryWrapper<SysRolePermission> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(SysRolePermission::getRoleId, roleIds)
               .eq(SysRolePermission::getDeleted, false);
        
        List<SysRolePermission> rolePermissions = sysRolePermissionMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(rolePermissions)) {
            return Collections.emptySet();
        }

        // 提取权限ID
        Set<Long> permissionIds = rolePermissions.stream()
                .map(SysRolePermission::getPermissionId)
                .collect(Collectors.toSet());

        // 查询权限详情
        LambdaQueryWrapper<SysPermission> permissionWrapper = new LambdaQueryWrapper<>();
        permissionWrapper.in(SysPermission::getId, permissionIds)
                       .eq(SysPermission::getDeleted, false)
                       .eq(SysPermission::getStatus, 1);
        
        List<SysPermission> permissions = sysPermissionMapper.selectList(permissionWrapper);
        return permissions.stream()
                .map(SysPermission::getCode)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
    }

    @Override
    @Cacheable(value = USER_ROLES_CACHE, key = "#userId")
    public Set<Long> getUserRoles(Long userId) {
        if (userId == null) {
            return Collections.emptySet();
        }

        // 查询用户角色关联
        LambdaQueryWrapper<SysUserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUserRole::getUserId, userId)
               .eq(SysUserRole::getDeleted, false);
        
        List<SysUserRole> userRoles = sysUserRoleMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(userRoles)) {
            return Collections.emptySet();
        }

        Set<Long> roleIds = userRoles.stream()
                .map(SysUserRole::getRoleId)
                .collect(Collectors.toSet());

        // 查询有效角色
        LambdaQueryWrapper<SysRole> roleWrapper = new LambdaQueryWrapper<>();
        roleWrapper.in(SysRole::getId, roleIds)
                  .eq(SysRole::getDeleted, false)
                  .eq(SysRole::getStatus, 1);
        
        List<SysRole> activeRoles = sysRoleMapper.selectList(roleWrapper);
        return activeRoles.stream()
                .map(SysRole::getId)
                .collect(Collectors.toSet());
    }

    @Override
    public boolean hasPermission(Long userId, String permission) {
        if (userId == null || permission == null || permission.trim().isEmpty()) {
            return false;
        }

        Set<String> userPermissions = getUserPermissions(userId);
        return userPermissions.contains(permission.trim());
    }

    @Override
    public boolean hasAnyPermission(Long userId, String... permissions) {
        if (userId == null || permissions == null || permissions.length == 0) {
            return false;
        }

        Set<String> userPermissions = getUserPermissions(userId);
        return Arrays.stream(permissions)
                .filter(Objects::nonNull)
                .map(String::trim)
                .filter(p -> !p.isEmpty())
                .anyMatch(userPermissions::contains);
    }

    @Override
    public boolean hasAllPermissions(Long userId, String... permissions) {
        if (userId == null || permissions == null || permissions.length == 0) {
            return false;
        }

        Set<String> userPermissions = getUserPermissions(userId);
        return Arrays.stream(permissions)
                .filter(Objects::nonNull)
                .map(String::trim)
                .filter(p -> !p.isEmpty())
                .allMatch(userPermissions::contains);
    }

    @Override
    @Cacheable(value = USER_MENUS_CACHE, key = "#userId")
    public Set<Long> getUserMenus(Long userId) {
        if (userId == null) {
            return Collections.emptySet();
        }

        // 获取用户角色
        Set<Long> roleIds = getUserRoles(userId);
        if (CollectionUtils.isEmpty(roleIds)) {
            return Collections.emptySet();
        }

        // 查询角色菜单关联
        LambdaQueryWrapper<SysRoleMenu> menuWrapper = new LambdaQueryWrapper<>();
        menuWrapper.in(SysRoleMenu::getRoleId, roleIds);
        
        List<SysRoleMenu> roleMenus = sysRoleMenuMapper.selectList(menuWrapper);
        if (CollectionUtils.isEmpty(roleMenus)) {
            return Collections.emptySet();
        }

        // 提取菜单ID
        return roleMenus.stream()
                .map(SysRoleMenu::getMenuId)
                .collect(Collectors.toSet());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {USER_ROLES_CACHE, USER_PERMISSIONS_CACHE, USER_MENUS_CACHE}, key = "#userId")
    public void assignRolesToUser(Long userId, List<Long> roleIds) {
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        if (CollectionUtils.isEmpty(roleIds)) {
            return;
        }

        // 先删除用户现有角色
        LambdaQueryWrapper<SysUserRole> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.eq(SysUserRole::getUserId, userId);
        sysUserRoleMapper.delete(deleteWrapper);

        // 批量插入新角色
        List<SysUserRole> userRoles = roleIds.stream()
                .distinct()
                .map(roleId -> {
                    SysUserRole userRole = new SysUserRole();
                    userRole.setUserId(userId);
                    userRole.setRoleId(roleId);
                    return userRole;
                })
                .collect(Collectors.toList());

        // 使用批量插入
        for (SysUserRole userRole : userRoles) {
            sysUserRoleMapper.insert(userRole);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {USER_ROLES_CACHE, USER_PERMISSIONS_CACHE, USER_MENUS_CACHE}, key = "#userId")
    public void removeUserRoles(Long userId, List<Long> roleIds) {
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        if (CollectionUtils.isEmpty(roleIds)) {
            return;
        }

        // 删除指定的用户角色关联
        LambdaQueryWrapper<SysUserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUserRole::getUserId, userId)
               .in(SysUserRole::getRoleId, roleIds);
        
        sysUserRoleMapper.delete(wrapper);
    }

    @Cacheable(value = USER_DEPT_PERMISSIONS_CACHE, key = "#userId + ':' + #departmentId")
    public Set<String> getUserPermissionsByDepartment(Long userId, Long departmentId) {
        if (userId == null || departmentId == null) {
            return Collections.emptySet();
        }

        // 验证用户是否属于该部门
        SysUser user = sysUserMapper.selectById(userId);
        if (user == null || Boolean.TRUE.equals(user.getDeleted()) || !Objects.equals(user.getDepartmentId(), departmentId)) {
            return Collections.emptySet();
        }

        // 获取用户权限（已包含部门验证）
        return getUserPermissions(userId);
    }

    public boolean hasPermissionInDepartment(Long userId, Long departmentId, String permission) {
        if (userId == null || departmentId == null || permission == null || permission.trim().isEmpty()) {
            return false;
        }

        Set<String> deptPermissions = getUserPermissionsByDepartment(userId, departmentId);
        return deptPermissions.contains(permission.trim());
    }

    @Override
    @CacheEvict(value = {USER_PERMISSIONS_CACHE, USER_ROLES_CACHE, USER_MENUS_CACHE, USER_DEPT_PERMISSIONS_CACHE}, key = "#userId")
    public void clearUserPermissionCache(Long userId) {
        log.info("清除用户权限缓存，用户ID: {}", userId);
    }

    @Override
    @CacheEvict(value = {USER_PERMISSIONS_CACHE, USER_ROLES_CACHE, USER_MENUS_CACHE, USER_DEPT_PERMISSIONS_CACHE}, allEntries = true)
    public void clearAllPermissionCache() {
        log.info("清除所有用户权限缓存");
    }

    /**
     * 获取用户角色ID集合（辅助方法）
     *
     * @param userId 用户ID
     * @return 角色ID集合
     */
    private Set<Long> getUserRoleIds(Long userId) {
        if (userId == null) {
            return Collections.emptySet();
        }

        try {
            LambdaQueryWrapper<SysUserRole> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysUserRole::getUserId, userId);
            
            List<SysUserRole> userRoles = sysUserRoleMapper.selectList(wrapper);
            return userRoles.stream()
                    .map(SysUserRole::getRoleId)
                    .collect(Collectors.toSet());

        } catch (Exception e) {
            log.error("获取用户角色ID失败，用户ID: {}", userId, e);
            return Collections.emptySet();
        }
    }
}